﻿using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Web.Hosting;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;
using System.DirectoryServices;
using System.DirectoryServices.AccountManagement;
using System.Collections.Generic;
using System.Web;


namespace Skupine_Web_Part.SkupineWP
{
    [ToolboxItem(false)]
    public partial class SkupineWP : WebPart, IWebEditable
    {
        protected override void OnInit(EventArgs e)
        {
            base.OnInit(e);
            InitializeControl();
        }
        public string ldapQuery { get; set; }
        public string opcije { get; set; }
        public string ou { get; set; }
        private static int i = 0;
        private static string _errors = "";
        public bool ExecutionTime { get; set; }
        public bool NumberOfObjects { get; set; }
        public bool ShowErrors { get; set; }




        //Display users who have permissions on current web
        private static void DisplaySiteUsers(TreeView treeView, string ldapQuery)
        {
            SPWeb web = SPContext.Current.Web;
            SPSite site = SPContext.Current.Site;
            string siteUrl = site.Url;
            SPList userList = site.RootWeb.SiteUserInfoList;
            Guid userListId = userList.ID;
            SPGroupCollection groups = web.Groups;
            SPUserCollection users = web.Users;
            using (HostingEnvironment.Impersonate())
            {
                PrincipalContext principalContext = new PrincipalContext(ContextType.Domain, ldapQuery);

                foreach (SPGroup spGroup in groups)
                {
                    i++;
                    TreeNode spGroupsTreeNode = new TreeNode(spGroup.Name);
                    spGroupsTreeNode.ImageUrl = siteUrl + @"/_layouts/images/skupine%20web%20part/group.png";
                    treeView.Nodes.Add(spGroupsTreeNode);
                    if (spGroup.OnlyAllowMembersViewMembership == false || spGroup.CanCurrentUserViewMembership)
                    {
                        spGroupsTreeNode.NavigateUrl = web.Url + @"/_layouts/userdisp.aspx?id=" + spGroup.ID;
                        try
                        {
                            foreach (SPUser spUser in spGroup.Users)
                            {
                                i++;
                                if (!spUser.IsDomainGroup)
                                {
                                    TreeNode userTreeNode = new TreeNode(spUser.Name);
                                    userTreeNode.NavigateUrl = siteUrl + @"/_layouts/listform.aspx?PageType=4&ListId=" +
                                                               userListId + @"&ID=" + spUser.ID;
                                    userTreeNode.ImageUrl = siteUrl + @"/_layouts/images/skupine%20web%20part/user.png";
                                    spGroupsTreeNode.ChildNodes.Add(userTreeNode);
                                }
                                if (spUser.IsDomainGroup)
                                {
                                    TreeNode userTreeNode = new TreeNode(spUser.Name);
                                    userTreeNode.NavigateUrl = siteUrl + @"/_layouts/listform.aspx?PageType=4&ListId=" +
                                                               userListId + @"&ID=" + spUser.ID;
                                    userTreeNode.ImageUrl = siteUrl +
                                                            @"/_layouts/images/skupine%20web%20part/Domaingroup.png";
                                    spGroupsTreeNode.ChildNodes.Add(userTreeNode);
                                    GetMembersOfAdGroup(spUser.Name, principalContext, userTreeNode, siteUrl, web,
                                                        userListId);
                                }
                            }
                        }
                        catch (Exception exception)
                        {
                            _errors += exception.Message + Environment.NewLine;
                        }
                    }
                }
                foreach (SPUser spUser in users)
                {
                    i++;
                    try
                    {
                        if (!spUser.IsDomainGroup)
                        {
                            TreeNode userTreeNode = new TreeNode(spUser.Name);
                            userTreeNode.NavigateUrl = siteUrl + @"/_layouts/listform.aspx?PageType=4&ListId=" +
                                                       userListId + @"&ID=" + spUser.ID;
                            userTreeNode.ImageUrl = siteUrl + @"/_layouts/images/skupine%20web%20part/user.png";
                            treeView.Nodes.Add(userTreeNode);
                        }
                        if (spUser.IsDomainGroup)
                        {
                            TreeNode userTreeNode = new TreeNode(spUser.Name);
                            userTreeNode.NavigateUrl = siteUrl + @"/_layouts/listform.aspx?PageType=4&ListId=" +
                                                       userListId + @"&ID=" + spUser.ID;
                            userTreeNode.ImageUrl = siteUrl + @"/_layouts/images/skupine%20web%20part/Domaingroup.png";
                            treeView.Nodes.Add(userTreeNode);
                            GetMembersOfAdGroup(spUser.Name, principalContext, userTreeNode, siteUrl, web, userListId);
                        }
                    }
                    catch (Exception exception)
                    {
                        _errors += exception.Message;
                    }
                }
                principalContext.Dispose();
            }
        }

        //Helper method to call members of security groups recursively
        private static void GetMembersOfAdGroup(string groupName, PrincipalContext principalContext, TreeNode treeNode, string siteUrl, SPWeb web, Guid userListId)
        {
            SPUserCollection users = web.AllUsers;
            GroupPrincipal groupPrincipal = GroupPrincipal.FindByIdentity(principalContext, IdentityType.SamAccountName, groupName);

            if (groupPrincipal != null)
            {
                try
                {
                    foreach (Principal principal in groupPrincipal.GetMembers(false))
                    {
                        i++;
                        var type = principal.GetType();
                        if (type == typeof(UserPrincipal))
                        {
                            try
                            {
                                UserPrincipal user = UserPrincipal.FindByIdentity(principalContext, principal.UserPrincipalName);
                                if (user != null)
                                {
                                    TreeNode userTreeNode = new TreeNode(principal.Name);
                                    try
                                    {
                                        string userEmail = user.EmailAddress;
                                        int userId = users.GetByEmail(userEmail).ID;
                                        userTreeNode.NavigateUrl = siteUrl + @"/_layouts/listform.aspx?PageType=4&ListId=" + userListId + @"&ID=" + userId;
                                    }
                                    catch (Exception exception)
                                    {
                                        userTreeNode.NavigateUrl = "";
                                        _errors += exception.Message + " " + user.Name + " " + Environment.NewLine;
                                    }
                                    finally
                                    {
                                        userTreeNode.ImageUrl = siteUrl + @"/_layouts/images/skupine%20web%20part/user.png";
                                        treeNode.ChildNodes.Add(userTreeNode);
                                        user.Dispose();
                                    }
                                }
                            }
                            catch (Exception exception)
                            {
                                _errors += exception.Message;
                                TreeNode userTreeNode=new TreeNode(principal.Name);
                                userTreeNode.NavigateUrl = "";
                                userTreeNode.ImageUrl = siteUrl + @"/_layouts/images/skupine%20web%20part/user.png";
                                treeNode.ChildNodes.Add(userTreeNode);
                            }
                        }
                        else
                        {
                            TreeNode groupTreeNode = new TreeNode(principal.Name);
                            groupTreeNode.ImageUrl = siteUrl + @"/_layouts/images/skupine%20web%20part/Domaingroup.png";
                            groupTreeNode.NavigateUrl = "";
                            treeNode.ChildNodes.Add(groupTreeNode);
                            GetMembersOfAdGroup(principal.SamAccountName, principalContext, groupTreeNode, siteUrl, web, userListId);
                        }
                    }
                }
                catch (Exception exception)
                {
                    _errors += exception.Message;
                }
                groupPrincipal.Dispose();
            }
        }



        //Display users and groups from specific OU
        private static void DisplayGroupsFromOu(PrincipalContext principalContext, TreeView treeView, string ldapQuery)
        {
            SPSite site = SPContext.Current.Site;
            string siteUrl = site.Url;

            UserPrincipal userPrincipal = new UserPrincipal(principalContext);
            userPrincipal.Enabled = true;
            PrincipalSearcher principalSearcher = new PrincipalSearcher(userPrincipal);
            PrincipalSearchResult<Principal> userResults = principalSearcher.FindAll();

            if (userResults != null)
            {
                foreach (UserPrincipal userResult in userResults)
                {
                    i++;
                    TreeNode userTreeNode = new TreeNode(userResult.DisplayName);
                    userTreeNode.ImageUrl = siteUrl + @"/_layouts/images/skupine%20web%20part/user.png";
                    treeView.Nodes.Add(userTreeNode);
                }
            }
            principalSearcher.Dispose();
            userPrincipal.Dispose();

            GroupPrincipal groupPrincipal = new GroupPrincipal(principalContext);
            groupPrincipal.IsSecurityGroup = true;

            PrincipalSearcher groupPrincipalSearcher = new PrincipalSearcher(groupPrincipal);
            PrincipalSearchResult<Principal> groupResults = groupPrincipalSearcher.FindAll();
            if (groupResults != null)
            {
                foreach (GroupPrincipal groupResult in groupResults)
                {
                    i++;
                    TreeNode groupTreeNode = new TreeNode(groupResult.Name);
                    groupTreeNode.ImageUrl = siteUrl + @"/_layouts/images/skupine%20web%20part/Domaingroup.png";
                    groupTreeNode.NavigateUrl = "";
                    treeView.Nodes.Add(groupTreeNode);
                    GetGroupMembers(groupResult.SamAccountName, groupTreeNode, siteUrl, ldapQuery);
                }
            }
            groupPrincipalSearcher.Dispose();
            groupPrincipal.Dispose();
        }

        //Helper method to call members of security groups from specific OU
        private static void GetGroupMembers(string groupName, TreeNode treeNode, string siteUrl, string ldapQuery)
        {
            using (HostingEnvironment.Impersonate())
            {
                PrincipalContext principalContext = new PrincipalContext(ContextType.Domain, ldapQuery);
                GroupPrincipal groupPrincipal = GroupPrincipal.FindByIdentity(principalContext,
                                                                              IdentityType.SamAccountName, groupName);
                if (groupPrincipal != null)
                {
                    foreach (Principal principal in groupPrincipal.GetMembers(false))
                    {
                        i++;
                        var type = principal.GetType();
                        if (type == typeof(UserPrincipal))
                        {
                            UserPrincipal user = UserPrincipal.FindByIdentity(principalContext, principal.SamAccountName);
                            if (user != null)
                            {
                                TreeNode userTreeNode = new TreeNode(principal.Name);
                                userTreeNode.NavigateUrl = "";
                                userTreeNode.ImageUrl = siteUrl + @"/_layouts/images/skupine%20web%20part/user.png";
                                treeNode.ChildNodes.Add(userTreeNode);
                                user.Dispose();
                            }
                        }
                        else
                        {
                            TreeNode groupTreeNode = new TreeNode(principal.Name);
                            groupTreeNode.ImageUrl = siteUrl + @"/_layouts/images/skupine%20web%20part/Domaingroup.png";
                            groupTreeNode.NavigateUrl = "";
                            treeNode.ChildNodes.Add(groupTreeNode);
                            GetGroupMembers(principal.SamAccountName, groupTreeNode, siteUrl, ldapQuery);
                        }
                    }
                    groupPrincipal.Dispose();
                    principalContext.Dispose();
                }
            }
        }

        private void Page_Load(object sender, EventArgs e)
        {

            if (!Page.IsPostBack)
            {
                Stopwatch stopwatch = new Stopwatch();
                stopwatch.Start();
                if (!ScriptManager.GetCurrent(Page).IsInAsyncPostBack)
                {
                    i = 0;
                    _errors = "";

                    if (opcije == "Display site users")
                    {
                        DisplaySiteUsers(TreeView1, ldapQuery);
                    }
                    if (opcije == "Display users and groups from specific OU")
                    {
                        if (!string.IsNullOrEmpty(ou))
                        {
                            try
                            {
                                using (HostingEnvironment.Impersonate())
                                {
                                    PrincipalContext principalContext = new PrincipalContext(ContextType.Domain, ldapQuery, ou);
                                    DisplayGroupsFromOu(principalContext, TreeView1, ldapQuery);
                                }

                            }
                            catch (Exception exception)
                            {
                                _errors += "Error querying Active Directory. Check your ldap filter. " + exception.Message;
                            }
                        }
                        else
                        {
                            try
                            {
                                using (HostingEnvironment.Impersonate())
                                {
                                    PrincipalContext principalContext = new PrincipalContext(ContextType.Domain,
                                                                                             ldapQuery);
                                    DisplayGroupsFromOu(principalContext, TreeView1, ldapQuery);
                                }
                            }
                            catch (Exception exception)
                            {
                                _errors += "Error querying Active Directory. Check your ldap filter. " + exception.Message;
                            }
                        }
                    }
                }
                stopwatch.Stop();
                TimeSpan ts = stopwatch.Elapsed;
                string elapsedTime = string.Format("{0:00}:{1:00}:{2:00}.{3:00}", ts.Hours, ts.Minutes, ts.Seconds,
                                                   ts.Milliseconds / 10);
                if (ExecutionTime)
                {
                    lblExecTime.Text = string.Format(@"Execution time: {0}", elapsedTime);
                }
                if (NumberOfObjects)
                {
                    lblNumberOfObjects.Text = string.Format(@"Number of users and groups loaded: {0}.", i);
                }

                if (!string.IsNullOrEmpty(_errors) && ShowErrors)
                {
                    lblErrors.Text = string.Format(@"There were some errors displaying users and groups: <strong>{0}</strong>", _errors);
                }
            }
        }

        EditorPartCollection IWebEditable.CreateEditorParts()
        {
            List<EditorPart> editors = new List<EditorPart>();
            SkupineEditor editorPart = new SkupineEditor();
            editorPart.ID = this.ID + "_editorPart";
            editors.Add(editorPart);
            return new EditorPartCollection(editors);
        }

        object IWebEditable.WebBrowsableObject
        {
            get
            {
                return this;
            }
        }
    }


}
